// Basic Types
let id: number = 5;
let company: string = "Traversy Media";
let isPublished: boolean = true;
let x: any = "hello";

let ids: number[] = [1, 2, 3, 4];
let arr: any[] = ["Hello", 1, true];

// Tuple: 数量与顺序必须一一对应
let person: [number, string, boolean] = [1, "1", true];
// Tuple Array
let employee: [number, string][] = [
  [1, "1"],
  [2, "2"],
];

// Union: 联合类型（其中之一即可）
let pid: string | number = 1;

// enum
enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}
// -> 4
console.log(Direction.Right);

// Objects
type User = {
  id: number;
  name: string;
};
const user: User = {
  id: 1,
  name: "Jerry",
};

// Type Assertion
let cid: any = 1;
let customerId = cid as number;

// Function
function addNum(x: number, y: number): number {
  return x + y;
}
function log(message: string | number): void {
  console.log(message);
}

// Interfaces
interface UserInterface {
  readonly id: number;
  name: string;
  age?: number;
}
const user1: UserInterface = {
  id: 1,
  name: "Tom",
};
interface MathFunc {
  (x: number, y: number): number;
}
const add: MathFunc = (x: number, y: number): number => x + y;
const sub: MathFunc = (x: number, y: number): number => x - y;

type Point = number | string;
const p1 = 1;

// Classes
interface PersonInterface {
  // 接口用于类时作用为 shape
  id: number;
  name: string;
  register(): string;
}
// implement: 接口的具体实现
class Person implements PersonInterface {
  id: number;
  name: string;

  // 类实例化时会首先自动调用构造函数的代码
  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  static log() {
    console.log("静态方法");
  }

  // 原型函数
  register() {
    return `${this.name} is now registered`;
  }
}

const Jerry = new Person(1, "Jerry");
Jerry.register();

// 继承
class Employee extends Person {
  position: string;

  constructor(id: number, name: string, position: string) {
    // super() 必须要在首行调用
    super(id, name);
    this.position = position;
  }
}
const emp = new Employee(2, "Tom", "Developer");

// Generics：泛型（类型变量）
function getArray<T>(items: T[]): T[] {
  return new Array().concat(items);
}
let numArr = getArray<number>([1, 2, 3]);
let strArr = getArray<string>(["1", "2", "3"]);
